package com.greate.community.service;

import com.greate.community.entity.DiscussPost;
import com.greate.community.entity.User;
import com.greate.community.entity.UserBehavior;
import com.greate.community.entity.UserTag;
import com.greate.community.util.CommunityConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 推荐服务
 * 基于用户行为和标签实现个性化推荐
 */
@Service
public class RecommendService implements CommunityConstant {

    private static final Logger logger = LoggerFactory.getLogger(RecommendService.class);

    // 行为类型常量
    private static final int BEHAVIOR_TYPE_VIEW = 0;
    private static final int BEHAVIOR_TYPE_LIKE = 1;
    private static final int BEHAVIOR_TYPE_COMMENT = 2;
    private static final int BEHAVIOR_TYPE_COLLECT = 3;

    @Resource
    private UserBehaviorService userBehaviorService;

    @Resource
    private UserTagService userTagService;

    @Resource
    private DiscussPostService discussPostService;

    @Resource
    private UserService userService;

    @Resource
    private LikeService likeService;

    @Resource
    private AIRecommendService aiRecommendService;

    /**
     * 为用户推荐帖子
     * @param userId 用户ID（0表示未登录用户）
     * @param offset 起始位置
     * @param limit 推荐数量
     * @return 推荐的帖子及其相关信息
     */
    public List<Map<String, Object>> recommendPosts(int userId, int offset, int limit) {
        try {
            if (userId <= 0) {
                // 未登录用户返回热门帖子
                List<DiscussPost> hotPosts = discussPostService.findHotPosts(offset, limit);
                return packagePostsWithUserInfo(hotPosts);
            }

            // 获取候选帖子
            List<DiscussPost> candidatePosts = discussPostService.findRecentPosts(0, 100);
            
            // 获取AI推荐分数
            Map<Integer, Double> aiScores = aiRecommendService.getAIRecommendations(userId, candidatePosts);
            
            // 计算综合分数
            Map<Integer, Double> finalScores = new HashMap<>();
            for (DiscussPost post : candidatePosts) {
                double behaviorScore = calculateBehaviorScore(userId, post.getId());
                double collaborativeScore = calculateCollaborativeScore(userId, post.getId());
                double contentScore = calculateContentSimilarityScore(userId, post.getId());
                double timeDecay = calculateTimeDecayFactor(post.getCreateTime());
                
                // 获取AI推荐分数，如果没有则使用默认值0.5
                double aiScore = aiScores.getOrDefault(post.getId(), 0.5);
                
                // 计算综合分数，加入AI推荐权重
                double finalScore = (behaviorScore * 0.3 + 
                                   collaborativeScore * 0.2 + 
                                   contentScore * 0.2 + 
                                   aiScore * 0.3) * timeDecay;
                
                finalScores.put(post.getId(), finalScore);
            }
            
            // 根据分数排序
            candidatePosts.sort((a, b) -> 
                Double.compare(finalScores.getOrDefault(b.getId(), 0.0),
                             finalScores.getOrDefault(a.getId(), 0.0)));
            
            // 返回指定数量的推荐帖子
            return packagePostsWithUserInfo(candidatePosts.subList(0, Math.min(limit, candidatePosts.size())));
            
        } catch (Exception e) {
            logger.error("推荐帖子时出错", e);
            // 发生错误时返回热门帖子
            List<DiscussPost> hotPosts = discussPostService.findHotPosts(offset, limit);
            return packagePostsWithUserInfo(hotPosts);
        }
    }

    /**
     * 计算用户行为分数
     * @param userId 用户ID
     * @param postId 帖子ID
     * @return 行为分数
     */
    private double calculateBehaviorScore(int userId, int postId) {
        // 获取用户对该帖子的所有行为
        List<UserBehavior> behaviors = userBehaviorService.getUserBehaviorsByEntityType(userId, ENTITY_TYPE_POST, 0, 100);
        if (behaviors == null || behaviors.isEmpty()) {
            return 0.0;
        }

        // 过滤出对特定帖子的行为
        behaviors = behaviors.stream()
                .filter(b -> b.getEntityId() == postId)
                .collect(Collectors.toList());

        if (behaviors.isEmpty()) {
            return 0.0;
        }

        double score = 0.0;
        for (UserBehavior behavior : behaviors) {
            switch (behavior.getBehaviorType()) {
                case BEHAVIOR_TYPE_VIEW:
                    score += 0.1;
                    break;
                case BEHAVIOR_TYPE_LIKE:
                    score += 0.3;
                    break;
                case BEHAVIOR_TYPE_COMMENT:
                    score += 0.5;
                    break;
                case BEHAVIOR_TYPE_COLLECT:
                    score += 0.7;
                    break;
            }
        }
        return Math.min(score, 1.0);
    }

    /**
     * 计算协同过滤分数
     * @param userId 用户ID
     * @param postId 帖子ID
     * @return 协同过滤分数
     */
    private double calculateCollaborativeScore(int userId, int postId) {
        // 获取相似用户
        List<User> similarUsers = userService.findSimilarUsers(userId, 10);
        if (similarUsers == null || similarUsers.isEmpty()) {
            return 0.0;
        }

        double score = 0.0;
        int count = 0;
        for (User similarUser : similarUsers) {
            List<UserBehavior> behaviors = userBehaviorService.getUserBehaviors(similarUser.getId(), postId,10);
            if (behaviors != null && !behaviors.isEmpty()) {
                for (UserBehavior behavior : behaviors) {
                    switch (behavior.getBehaviorType()) {
                        case BEHAVIOR_TYPE_VIEW:
                            score += 0.1;
                            break;
                        case BEHAVIOR_TYPE_LIKE:
                            score += 0.3;
                            break;
                        case BEHAVIOR_TYPE_COMMENT:
                            score += 0.5;
                            break;
                        case BEHAVIOR_TYPE_COLLECT:
                            score += 0.7;
                            break;
                    }
                }
                count++;
            }
        }
        return count > 0 ? Math.min(score / count, 1.0) : 0.0;
    }

    /**
     * 计算内容相似度分数
     * @param userId 用户ID
     * @param postId 帖子ID
     * @return 内容相似度分数
     */
    private double calculateContentSimilarityScore(int userId, int postId) {
        // 获取用户感兴趣的标签
        List<UserTag> userTags = userTagService.getUserTags(userId);
        if (userTags == null || userTags.isEmpty()) {
            return 0.0;
        }

        // 获取帖子标签
        List<String> postTags = discussPostService.getPostTags(postId);
        if (postTags == null || postTags.isEmpty()) {
            return 0.0;
        }

        // 计算标签匹配度
        int matchCount = 0;
        for (UserTag userTag : userTags) {
            if (postTags.contains(userTag.getTagName())) {
                matchCount++;
            }
        }

        return (double) matchCount / Math.max(userTags.size(), postTags.size());
    }

    /**
     * 计算时间衰减因子
     * @param createTime 创建时间
     * @return 时间衰减分数
     */
    private double calculateTimeDecayFactor(Date createTime) {
        long currentTimeMillis = System.currentTimeMillis();
        long postTimeMillis = createTime.getTime();
        // 使用指数衰减函数，半衰期为7天
        return Math.exp(-0.1 * (currentTimeMillis - postTimeMillis) / (7 * 24 * 60 * 60 * 1000));
    }

    /**
     * 将帖子列表封装为包含用户信息的结果
     * @param posts 帖子列表
     * @return 帖子和用户信息
     */
    private List<Map<String, Object>> packagePostsWithUserInfo(List<DiscussPost> posts) {
        List<Map<String, Object>> result = new ArrayList<>();
        if (posts != null) {
            for (DiscussPost post : posts) {
                Map<String, Object> map = new HashMap<>();
                map.put("post", post);
                
                User user = userService.findUserById(post.getUserId());
                // 如果找不到用户，跳过该帖子
                if (user == null) {
                    continue;
                }
                map.put("user", user);
                
                // 新增：点赞数量
                long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId());
                map.put("likeCount", likeCount);
                
                result.add(map);
            }
        }
        return result;
    }
} 